#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# # author : cypro666
# # date   : 2015.08.01
# # wrapper of svm method in sklearn
import sys, json, time
import numpy as np
from threading import Thread
from sklearn import svm

from magic3.utils import Timer
from magic3.filesystem import *
add_sys_path(grand_dir(__file__))

from skt.base import MethodBase
from skt.utils import _normalize, make_options


class SVM(MethodBase):
    def __init__(self, parameters={}):
        super().__init__(parameters)

    @property
    def name(self): return 'SVM'

    def output(self, cls):
        self.Log('output')
        super().output()
        extra = {}

        try:    extra['support'] = [float(i) for i in cls.support_]
        except: pass

        try:    extra['support_vectors'] = [list(v) for v in cls.support_vectors_]
        except: pass

        try:    extra['n_support'] = [float(i) for i in cls.n_support_]
        except: pass

        try:    extra['dual_coef'] = [list(v) for v in cls.dual_coef_]
        except: pass

        try:    extra['coef'] = [float(i) for i in cls.coef_]
        except: pass

        try:    extra['intercept'] = [float(i) for i in cls.intercept_]
        except: pass

        fn = self.json_name()
        json.dump(extra, open(fn, 'w'), indent=4)

    def execute(self):
        self.read_input()
        self._normalize(False, self._param['normalize'])

        if self._param['coef0'] > 1.0:
            self._param['coef0'] = 1.0

        if self._param['gamma'] < 1E-3:
            self._param['gamma'] = 1E-3

        if self._param['degree'] > 5 or self._param['degree'] < 2:
            self._param['degree'] = 3

        if self._param['tol'] < 1E-6:
            self._param['tol'] = 1E-6

        if self._param['max_iter'] > 10000:
            self._param['max_iter'] = 10000

        self.save_parameters()

        cls = svm.SVC(kernel=self._param['kernel'],
                      cache_size=int(self._param['cache_size']),
                      coef0=self._param['coef0'],
                      gamma=self._param['gamma'],
                      degree=self._param['degree'],
                      tol=self._param['tol'],
                      max_iter=self._param['max_iter'],
                      shrinking=True,
                      random_state=None,
                      probability=self._param['probability'] != '0',
                      verbose=False)

        cls.fit(self._train, self._label)

        self._results = cls.predict(self._testing)
        self.output(cls)

    def run(self, timeout):
        t = Thread(target=self.execute)
        t.start()
        t.join(timeout)
        if t.is_alive():
            self.Log('timeout!')
        self.Log('exit')


if __name__ == '__main__':
    opts = [('train_file', 'str', []),
            ('label_file', 'str', []),
            ('testing_file', 'str', []),
            ('results_file', 'str', []),
            ('log_file', 'str', []),
            ('normalize', 'choice', ['0', '1', '2']),
            ('cache_size', 'choice', ['64', '256', '1024', '4096']),
            ('kernel', 'choice', ['linear', 'poly', 'rbf', 'sigmoid', 'precomputed']),
            ('probability', 'choice', ['0', '1']),
            ('gamma', 'float', []),
            ('coef0', 'float', []),
            ('tol', 'float', []),
            ('degree', 'int', []),
            ('max_iter', 'int', [])]

    parameters = make_options(opts)
    timer = Timer()

    SVM(parameters).run(3600 * 4)

    if __debug__:
        print('elapsed:', timer)



